﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.ComponentModel;

namespace SkeletalAnimation3D.Core
{
    public class Skeleton : ObservableCollection<Bone>, INotifyPropertyChanged
    {
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Bone Root
        {
            get
            {
                if (this.Count == 0)
                {
                    return null;
                }
                else
                {
                    return this[0];
                }
            }
            set
            {
                this.Clear();
                this.Add(value);
            }
        }

        internal Int32Collection GetAttachedPoints(int boneId)
        {
            if (Root != null)
            {
                return Root.GetAttachedPoints(boneId);
            }
            else
            {
                return new Int32Collection();
            }
        }

        internal DoubleCollection GetPointWeights(int boneId)
        {
            if (Root != null)
            {
                return Root.GetPointWeights(boneId);
            }
            else
            {
                return new DoubleCollection();
            }
        }

        internal BoneInfo GetBoneInfo()
        {
            if (Root != null)
            {
                return Root.GetBoneInfo();
            }
            else
            {
                return null;
            }
        }

        internal void CopyBoneData(SkeletonInfo target)
        {
            if (Root != null)
            {
                Root.CopyBoneData(target);
            }
        }

        internal bool SetBoneSize(int boneId, double size)
        {
            if (Root != null)
            {
                if (Root.SetBoneSize(boneId, size))
                {
                    OnPropertyChanged(new PropertyChangedEventArgs("Skeleton"));
                    return true;
                }
            }
            return false;
        }

        internal bool SetBoneName(int boneId, string name)
        {
            if (Root != null)
            {
                if(Root.SetBoneName(boneId, name))
                {
                    OnPropertyChanged(new PropertyChangedEventArgs("Skeleton"));
                    return true;
                }
            }
            return false;
        }

        internal bool MoveBone(int boneId, Vector3D offset)
        {
            if (Root != null)
            {
                if(Root.MoveBone(boneId, offset))
                {
                    OnPropertyChanged(new PropertyChangedEventArgs("Skeleton"));
                    return true;
                }
            }
            return false;
        }

        internal int GetNewBoneId()
        {
            if (Root != null)
            {
                return Root.GetMaxBoneId() + 1;
            }
            else
            {
                return 0;
            }
        }

        internal bool AddBone(int parentBoneId, int newId, string name, Point3D position, double size)
        {
            if (Root != null)
            {
                if (Root.AddBone(parentBoneId, newId, name, position, size))
                {
                    OnPropertyChanged(new PropertyChangedEventArgs("Root"));
                    return true;
                }
            }
            return false;
        }

        internal bool AttachPointsToBone(int boneId, Int32Collection pointIds)
        {
            if (Root != null)
            {
                if (Root.AttachPointsToBone(boneId, pointIds))
                {
                    OnPropertyChanged(new PropertyChangedEventArgs("Root"));
                    return true;
                }
            }
            return false;
        }

        internal bool DetachPointsFromBone(int boneId, Int32Collection pointIds)
        {
            if (Root != null)
            {
                if (Root.DetachPointsFromBone(boneId, pointIds))
                {
                    OnPropertyChanged(new PropertyChangedEventArgs("Root"));
                    return true;
                }
            }
            return false;
        }

        internal bool SetPointWeightsOnBone(int boneId, Int32Collection pointIds, double weight)
        {
            if (Root != null)
            {
                if (Root.SetPointWeightsOnBone(boneId, pointIds, weight))
                {
                    OnPropertyChanged(new PropertyChangedEventArgs("Root"));
                    return true;
                }
            }
            return false;
        }

        public Bone GetBoneById(int boneId)
        {
            if (Root != null)
            {
                return Root.GetBone(boneId);
            }
            else
            {
                return null;
            }
        }
    }
}